package org.springblade.modules.notice.core.receiver;

import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.notice.constant.PushObjectConstant;
import org.springblade.modules.notice.enums.PushObjectEnum;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author ysq
 * @Date 2024/11/26
 * @Description 接收对象抽象处理器
 */
@Slf4j
public abstract class BasePushObjectHandler implements PushObjectHandler {

	/**
	 * 对应渠道
	 * 子类初始化时需指定
	 * @see PushObjectEnum
	 */
	protected Integer pushObjectCode;
	@Resource
	private PushObjectFactory pushObjectFactory;
	@Resource
	protected JdbcTemplate jdbcTemplate;

	/**
	 * 存储所有接收对象类型的sql语句
	 */
	protected static Map<String, String> receiverSqlMap = new HashMap<>(16);
	static {
		for (PushObjectEnum pushObjectEnum : PushObjectEnum.values()) {
			try {
				// 通过反射获取常量对象
				Class<?> clazz = PushObjectConstant.class;
				Field[] fields = clazz.getFields();
				for (Field field : fields) {
					String fieldName = field.getName();
					if (fieldName.equals(String.format("P_%s", pushObjectEnum.getCode()))) {
						Object fieldValue = field.get(null);
						receiverSqlMap.put(fieldName, fieldValue.toString());
					}
				}
			} catch (IllegalAccessException e) {
				continue;
			}
		}
	}

	@PostConstruct
	private void init() {
		pushObjectFactory.register(pushObjectCode, this);
	}

	/**
	 * 各子类消息处理逻辑
	 */
	public abstract Set<String> handle(Long id, String pushTypeField) throws Exception;

	/**
	 * 默认处理逻辑
	 * @param id
	 * @param pushTypeField
	 * @return
	 */
	public Set<String> defaultHandle(Long id, String pushTypeField) {
		String receiverSql = receiverSqlMap.get(String.format("P_%s", pushObjectCode));
		if (Func.isBlank(receiverSql)) {
			return null;
		}

		List<Map<String, Object>> list =jdbcTemplate.query(receiverSql, new Object[]{id}, new ColumnMapRowMapper());
		return list.stream().filter(e -> e.get(pushTypeField) != null).map(e -> e.get(pushTypeField).toString()).collect(Collectors.toSet());
	}

	@Override
	public Set<String> getPushReceivers(Long id, String pushTypeField) {
        try {
            return handle(id, pushTypeField);
        } catch (Exception e) {
			log.warn("获取接收人失败，pushObjectCode:{},id:{},pushTypeField:{},fail:{}", PushObjectEnum.getDesc(pushObjectCode), id, pushTypeField, Throwables.getStackTraceAsString(e));
            return null;
        }
    }

}
